package com.xc.quickstart.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.xc.quickstart.common.constant.RedisKeyConstant;
import com.xc.quickstart.common.context.CommonContext;
import com.xc.quickstart.infrastructure.redis.RedisService;
import com.xc.quickstart.service.JobDailyReportService;
import com.xc.quickstart.service.dto.JobDailyReportDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class JobDailyReportServiceImpl implements JobDailyReportService {

    @Autowired
    private RedisService redisService;

    @Override
    public void record(String className, String jobName, Long costTime, boolean isSuccess) {
        // 参数准备
        long executeCount = 0L;
        long successCount = 0L;
        long failCount = 0L;
        long averageCostTime = 0L;

        String key = String.format(RedisKeyConstant.JOB_DAILY_REPORT_KEY, getJobDailyReportKey(new Date()));

        // 从redis获取当前job是否执行情况
        if (redisService.hexists(key, className)) {
            JobDailyReportDTO cacheReportDTO = JSON.parseObject(redisService.hget(key, className), JobDailyReportDTO.class);
            if (Objects.nonNull(cacheReportDTO)) {
                executeCount = cacheReportDTO.getExecuteCount();
                successCount = cacheReportDTO.getSuccessCount();
                failCount = cacheReportDTO.getFailCount();
                averageCostTime = cacheReportDTO.getAverageCostTime();
            }
        }

        // 保存job执行数据到redis
        JobDailyReportDTO jobDailyReportDTO = new JobDailyReportDTO();
        jobDailyReportDTO.setClassName(className);
        jobDailyReportDTO.setJobName(jobName);
        jobDailyReportDTO.setExecuteCount(executeCount + 1);
        jobDailyReportDTO.setSuccessCount(isSuccess ? successCount + 1 : successCount);
        jobDailyReportDTO.setFailCount(!isSuccess ? failCount + 1 : failCount);

        if (isSuccess) {
            averageCostTime = (averageCostTime * successCount + costTime) / jobDailyReportDTO.getSuccessCount();
        }

        jobDailyReportDTO.setAverageCostTime(averageCostTime);
        redisService.hset(key, className, JSON.toJSONString(jobDailyReportDTO));

        // 设置失效时间为48小时
        redisService.expire(key, 48L, TimeUnit.HOURS);
    }

    private String getJobDailyReportKey(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        if (calendar.get(Calendar.HOUR_OF_DAY) > 8) {
            return DateUtil.format(DateUtils.addDays(date, 1), CommonContext.YYYYMMDD);
        }

        return DateUtil.format(date, CommonContext.YYYYMMDD);
    }

}
